package com.frcdi.qms.web.controller.common;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.druid.pool.DruidDataSource;
import com.frcdi.qms.common.annotation.Log;
import com.frcdi.qms.common.config.QmsConfig;
import com.frcdi.qms.common.constant.Constants;
import com.frcdi.qms.common.core.controller.BaseController;
import com.frcdi.qms.common.core.domain.AjaxResult;
import com.frcdi.qms.common.core.domain.entity.SysUser;
import com.frcdi.qms.common.core.domain.model.LoginUser;
import com.frcdi.qms.common.core.page.TableDataInfo;
import com.frcdi.qms.common.enums.BusinessType;
import com.frcdi.qms.common.utils.DateUtils;
import com.frcdi.qms.common.utils.SecurityUtils;
import com.frcdi.qms.common.utils.StringUtils;
import com.frcdi.qms.common.utils.file.FileUploadUtils;
import com.frcdi.qms.common.utils.file.FileUtils;
import com.frcdi.qms.common.utils.ip.IpUtils;
import com.frcdi.qms.common.config.jdbc.JdbcUtils;
import com.frcdi.qms.common.utils.poi.ExcelUtil;
import com.frcdi.qms.common.utils.sql.MysqlBackupUtils;
import com.frcdi.qms.system.domain.DatabaseBackup;
import com.frcdi.qms.system.domain.SysUserOperLog;
import com.frcdi.qms.system.service.IDatabaseBackupService;
import com.frcdi.qms.system.service.ISysDeptService;
import com.frcdi.qms.system.service.ISysUserOperLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 数据备份Controller
 *
 * @author semarl
 * @date 2022-02-11
 */
@RestController
@RequestMapping("/system/databaseBackup")
public class DatabaseBackupController extends BaseController {
    @Autowired
    private IDatabaseBackupService databaseBackupService;

    @Autowired
    private DruidDataSource druidDataSource;
    @Autowired
    private ISysDeptService deptService;

    @Autowired
    private ISysUserOperLogService operLogService;

    @Autowired
    private JdbcUtils jdbcUtils;




    /**
     * 获取主机地址
     */
    private String getHost() {
        Map<String, String> dbInfo = jdbcUtils.getDatabaseBackupDBInfo();
        return dbInfo.get("host");
        /*String url = druidDataSource.getUrl();
        if(url.indexOf("3306")>=0){
            return url.substring(url.indexOf("mysql"), url.indexOf("3306")).replace(":", "").replace("//", "").replace("mysql", "");
        }else{
            return url.substring(url.indexOf("mysql"), url.indexOf("3307")).replace(":", "").replace("//", "").replace("mysql", "");
        }*/
    }

    /**
     * 获取数据库名
     */
    private String getDataBaseName() {
        Map<String, String> dbInfo = jdbcUtils.getDatabaseBackupDBInfo();
        return  dbInfo.get("dbName");
        /*String url = druidDataSource.getUrl();
        if(url.contains("3306")){
            return url.substring(url.indexOf("3306"), url.indexOf("?")).replaceAll("/", "").replaceAll("3306", "");
        }else{
            return url.substring(url.indexOf("3307"), url.indexOf("?")).replaceAll("/", "").replaceAll("3307", "");
        }*/
    }

    /**
     * 获取数据库端口号
     */
    private String getDataBasePort() {
        Map<String, String> dbInfo = jdbcUtils.getDatabaseBackupDBInfo();
        return  dbInfo.get("port");
    }

    /**
     * 获取数据库密码
     */
    private String getDataBasePassword() {
        Map<String, String> dbInfo = jdbcUtils.getDatabaseBackupDBInfo();
        return  dbInfo.get("passWord");
    }

    /**
     * 查询数据备份列表
     */
    @GetMapping("/list")
    public TableDataInfo list(DatabaseBackup databaseBackup) {
        startPage();
        List<DatabaseBackup> list = databaseBackupService.selectDatabaseBackupList(databaseBackup);
        return getDataTable(list);
    }

    /**
     * 导出数据备份列表
     */
    @Log(title = "数据备份", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, DatabaseBackup databaseBackup) throws Exception{
        List<DatabaseBackup> list = databaseBackupService.selectDatabaseBackupList(databaseBackup);
        ExcelUtil<DatabaseBackup> util = new ExcelUtil<DatabaseBackup>(DatabaseBackup.class);
        util.exportExcel(response, list, "数据备份数据");
    }

    /**
     * 获取数据备份详细信息
     */
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return AjaxResult.success(databaseBackupService.selectDatabaseBackupById(id));
    }

    /**
     * 新增数据备份
     */
    @Log(title = "数据备份", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody DatabaseBackup databaseBackup) {
        //先进行数据库备份
        String savePath = QmsConfig.getBackupPath();
        String fileName = DateUtil.format(new Date(), "yyyyMMdd-HHmmss") + "-" + RandomUtil.randomNumbers(4) + ".sql";
        boolean flag = MysqlBackupUtils.backup(getHost(),druidDataSource.getUsername(), druidDataSource.getPassword(),  savePath, fileName, getDataBaseName(),getDataBasePort());
        if (flag) {
            databaseBackup.setName(fileName);
            databaseBackup.setRemark(savePath);
            Long fileSize = FileUtil.file(new File(savePath, fileName)).length();
            String dbSize = "";
            DecimalFormat df = new DecimalFormat("#");
            if (fileSize < 1024) {
                dbSize = df.format((double) fileSize) + "BT";
            } else if (fileSize < 1048576) {
                dbSize = df.format((double) fileSize / 1024) + "KB";
            } else if (fileSize < 1073741824) {
                dbSize = df.format((double) fileSize / 1048576) + "MB";
            } else {
                dbSize = df.format((double) fileSize / 1073741824) + "GB";
            }
            databaseBackup.setDbSize(dbSize);
            databaseBackup.setRemark(savePath);
            databaseBackup.setCreateBy(SecurityUtils.getUsername());
            return toAjax(databaseBackupService.insertDatabaseBackup(databaseBackup));
        } else {
            return AjaxResult.error("备份失败，请联系管理员");
        }
    }

    @Log(title = "数据备份", businessType = BusinessType.IMPORT)
    @GetMapping("/restore/{id}")
    public AjaxResult restore(@PathVariable("id") Long id, HttpServletResponse response, HttpServletRequest request) throws IOException {
        DatabaseBackup databaseBackup = databaseBackupService.selectDatabaseBackupById(id);
        if (databaseBackup != null) {
            String fileName = databaseBackup.getName();
            String savePath = databaseBackup.getRemark();
            boolean flag = MysqlBackupUtils.recover(savePath + File.separator + fileName, getHost(), getDataBaseName(), druidDataSource.getUsername(), druidDataSource.getPassword(),getDataBasePort());
            if (flag) {
                //添加操作日志
                String str = StringUtils.getFieldAnnotation(databaseBackup);
                if(StringUtils.isNotEmpty(str)){// 日志记录
                    SysUserOperLog operLog = new SysUserOperLog();
                    operLog.setModelName("系统管理");
                    operLog.setTableName("数据备份恢复");
                    operLog.setType(BusinessType.INSERT.ordinal());
                    // 获取当前的用户
                    LoginUser loginUser = SecurityUtils.getLoginUser();
                    operLog.setOperId(loginUser.getUsername());
                    operLog.setOperName(loginUser.getUser().getNickName());
                    operLog.setDeptName(deptService.getDeptName(loginUser.getDeptId()));
                    operLog.setOperIp(IpUtils.getIpAddr());
                    operLog.setOperAfter(str);
                    operLog.setOperTime(DateUtils.getNowDate());
                    operLogService.insertSysUserOperLog(operLog);
                }
                return toAjax(1);
            }
        }


        return AjaxResult.error("还原失败，请联系管理员");
    }

    @Log(title = "数据备份", businessType = BusinessType.IMPORT)
    @PostMapping("/restoreFromFile")
    public AjaxResult restoreFromFile(MultipartFile file) throws IOException {
        try
        {
            // 上传文件路径
            String filePath = QmsConfig.getUploadPath();
            // 上传并返回新文件名称
            String fileName = FileUploadUtils.upload(filePath,file);
            fileName = fileName.substring((Constants.RESOURCE_PREFIX+File.separator+"upload").length());
            System.out.println("filePath>>>"+filePath + File.separator + fileName);
            boolean flag = MysqlBackupUtils.recover(filePath + File.separator + fileName, getHost(), getDataBaseName(), druidDataSource.getUsername(), druidDataSource.getPassword(),getDataBasePort());
            if (flag) {
                return toAjax(1);
            }
            return AjaxResult.error("还原失败，请联系管理员");
        }
        catch (Exception e)
        {
            return AjaxResult.error(e.getMessage());
        }
    }


    @Log(title = "数据备份", businessType = BusinessType.EXPORT)
    @GetMapping("/download/{id}")
    public void download(@PathVariable("id") Long id, HttpServletResponse response, HttpServletRequest request) throws IOException {
        DatabaseBackup data = databaseBackupService.selectDatabaseBackupById(id);
        if (data != null) {
            String fileName = data.getName();
            String savePath = data.getRemark();
            String realFileName = System.currentTimeMillis() + "_" + fileName;
            String filePath = savePath + File.separator + fileName;
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, realFileName);
            FileUtils.writeBytes(filePath, response.getOutputStream());

            //添加操作日志
            String str = StringUtils.getFieldAnnotation(data);
            if(StringUtils.isNotEmpty(str)){// 日志记录
                SysUserOperLog operLog = new SysUserOperLog();
                operLog.setModelName("系统管理");
                operLog.setTableName("数据备份恢复");
                operLog.setType(BusinessType.OTHER.ordinal());
                // 获取当前的用户
                LoginUser loginUser = SecurityUtils.getLoginUser();
                operLog.setOperId(loginUser.getUsername());
                operLog.setOperName(loginUser.getUser().getNickName());
                operLog.setDeptName(deptService.getDeptName(loginUser.getDeptId()));
                operLog.setOperIp(IpUtils.getIpAddr());
                operLog.setOperAfter(str);
                operLog.setOperTime(DateUtils.getNowDate());
                operLogService.insertSysUserOperLog(operLog);
            }
        }
    }

    /**
     * 修改数据备份
     */
    @PreAuthorize("@ss.hasPermi('system:databaseBackup:edit')")
    @Log(title = "数据备份", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody DatabaseBackup databaseBackup) {
        return toAjax(databaseBackupService.updateDatabaseBackup(databaseBackup));
    }

    /**
     * 删除数据备份
     */
    @PreAuthorize("@ss.hasPermi('system:databaseBackup:remove')")
    @Log(title = "数据备份", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        return toAjax(databaseBackupService.deleteDatabaseBackupByIds(ids));
    }

    public Long getRoleId(){
        Long roleId = null;
        SysUser user = SecurityUtils.getLoginUser().getUser();
        if(user.getRoles().size() > 0){
            roleId = user.getRoles().get(0).getRoleId();
        }
        return roleId;
    }
}
